home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / a_utils / decomp.lha / decomp / tables.c < prev    next >
C/C++ Source or Header  |  1988-01-12  |  7KB  |  364 lines

  1. /*
  2.  * Module: tables.c
  3.  *
  4.  * Author: J. Reuter
  5.  *
  6.  * The functions in this module are used to make the first pass over
  7.  * a functions code and add information to the symbol and label tables.
  8.  */
  9.  
  10. #include "defs.h"
  11. #include "machine.h"
  12. #include "labeltab.h"
  13. #include "objfile.h"
  14. #include "vartab.h"
  15.  
  16. /*
  17.  * The tables() function makes a pass through a function's code.
  18.  * While processing the code, it builds several tables.  These
  19.  * include register and automatic (stack) local variable usage,
  20.  * branch targets (for building basic blocks), and global symbol
  21.  * usage (to determine type).
  22.  */
  23.  
  24. tables( addr, end_addr )
  25. address addr, end_addr;
  26. {
  27.     unsigned char ins;
  28.     address insaddr;
  29.     unsigned char mode;
  30.     register int argtype, amode, argno, argval;
  31.     register int rn, type, fl;
  32.     short offset;
  33.     struct nlist *s;
  34.     struct relocation_info *r;
  35.  
  36.     /* initialize pass */
  37.     relo_first();
  38.     r = relo_next();
  39.  
  40.     /* loop across all the instructions in this function */
  41.     while ( addr < end_addr ) {
  42.  
  43.     argval = 0;
  44.     ins = get_byte( addr );
  45.     addr += 1;
  46.  
  47.     /* process all the operands for the instruction */
  48.     for (argno = 0; argno < opcode[ins].numargs; argno++) {
  49.  
  50.         argtype = opcode[ins].argtype[argno];
  51.         if (is_branch_disp(argtype)) {
  52.         mode = 0xAF + ( (typelen(argtype) & ~T_UNSIGNED) << 4);
  53.         } else {
  54.         mode = get_byte( addr );
  55.         addr += 1;
  56.         }
  57.  
  58.         while ( r != NULL && addr > r->r_address )
  59.         r = relo_next();
  60.  
  61.         rn = regnm( mode );
  62.         type = typelen( argtype );
  63.         amode = addrmode( mode );
  64.  
  65.         fl = 0;
  66.  
  67.         if ( acctype( argtype ) == ACCW || acctype( argtype ) == ACCM )
  68.         fl |= C_WRITTEN;
  69.         if ( type & T_UNSIGNED )
  70.         fl |= T_UNSIGNED;
  71.  
  72.         if ( r != NULL && addr == r->r_address ) {
  73.  
  74.         if ( amode == LONGDISP || amode == LONGDISPDEF ) {
  75.  
  76.             argval = getdisp(addr, 4, rn, amode);
  77.             addr += 4;
  78.  
  79.         } else if ( amode == AUTOINC ) {
  80.  
  81.             if ( rn != PC ) {
  82.             fprintf( stderr, "ERR: strange relo autoinc reg\n" );
  83.             } else {
  84.             /* immediate values */
  85.             switch ( type & ~T_UNSIGNED ) {
  86.             case TYPL:
  87.                 argval = getdisp(addr, 4, rn, amode);
  88.                 addr += 4;
  89.                 break;
  90.  
  91.             default:
  92.                 fprintf( stderr, "ERR: strange relo autoinc %d\n",
  93.                     type );
  94.                 break;
  95.             }
  96.             }
  97.  
  98.         } else {
  99.             fprintf( stderr, "ERR: bad relo mode %d\n", amode );
  100.         }
  101.  
  102.         if ( r->r_extern ) {
  103.  
  104.             s = &symtab[r->r_symbolnum];
  105.  
  106.             if ( s->n_type == (N_EXT+N_UNDF) ) {
  107.  
  108.             if ( amode == LONGDISP || amode == AUTOINC ) {
  109.                 reg_add( rn, T_LONG, 0 );
  110.                 ext_add( r->r_symbolnum, type, argval, fl );
  111.             } else if ( amode == LONGDISPDEF ) {
  112.                 reg_add( rn, T_LONG, 0 );
  113.                 ext_add( r->r_symbolnum, type | T_POINTER,
  114.                     argval, fl );
  115.             } else {
  116.                 fprintf( stderr, "ERR: ext relo mode %d\n", amode );
  117.             }
  118.             } else {
  119.             fprintf( stderr, "ERR: ext relo type %d\n", s->n_type );
  120.             }
  121.  
  122.         } else {        /* not r->r_extern */
  123.  
  124.             if ( amode == LONGDISP || amode == LONGDISPDEF ) {
  125.  
  126.             if ( amode == LONGDISPDEF )
  127.                 type |= T_POINTER;
  128.  
  129.             if ( rn == PC ) {
  130.                 switch ( r->r_symbolnum ) {
  131.                 case 4:
  132.                 /* static function */
  133.                 int_add( argval, type, C_STATIC, C_TEXT );
  134.                 break;
  135.                 case 5:
  136.                 /* global function */
  137.                 int_add( argval, type, 0, C_TEXT );
  138.                 break;
  139.                 case 6:
  140.                 /* static data, const, string */
  141.                 int_add( argval, type, C_STATIC+fl, C_DATA );
  142.                 break;
  143.                 case 7:
  144.                 /* global data, const, string */
  145.                 int_add( argval, type, fl, C_DATA );
  146.                 break;
  147.                 case 8:
  148.                 /* static bss */
  149.                 int_add( argval, type, C_STATIC+fl, C_BSS );
  150.                 break;
  151.                 default:
  152.                 fprintf( stderr, "ERR: bad relo symbolnum %d\n",
  153.                     r->r_symbolnum );
  154.                 break;
  155.                 }
  156.             } else {
  157.                 /* other registers? */
  158.             }
  159.  
  160.             } else if ( amode == AUTOINC ) {
  161.  
  162.             switch ( r->r_symbolnum ) {
  163.             case 6:
  164.                 /* static data */
  165.                 int_add( argval, type, C_STATIC+fl, C_DATA );
  166.                 break;
  167.             case 8:
  168.                 /* static bss */
  169.                 int_add( argval, type, C_STATIC+fl, C_BSS );
  170.                 break;
  171.             default:
  172.                 fprintf( stderr, "ERR: auto relo symnum %d\n",
  173.                     r->r_symbolnum );
  174.                 break;
  175.             }
  176.  
  177.             } else {
  178.             fprintf( stderr, "ERR: int relo mode %d\n", amode );
  179.             }
  180.         }
  181.  
  182.         } else {        /* no relo info */
  183.  
  184.         switch (amode) {
  185.         case LITSHORT:
  186.         case LITUPTO31:
  187.         case LITUPTO47:
  188.         case LITUPTO63:
  189.             argval = mode;
  190.             break;
  191.  
  192.         case INDEX:
  193.             reg_add( rn, T_LONG, 0 );
  194.             argno--;
  195.             break;
  196.  
  197.         case REG:
  198.             reg_add( rn, type, fl );
  199.             break;
  200.  
  201.         case REGDEF:
  202.             reg_add( rn, type | T_POINTER, 0 );
  203.             break;
  204.  
  205.         case AUTODEC:
  206.             reg_add( rn, type | T_POINTER, 0 );
  207.             break;
  208.  
  209.         case AUTOINC:
  210.             if ( rn != PC ) {
  211.             reg_add( rn, type | T_POINTER, 0 );
  212.             } else {
  213.             /* immediate values */
  214.             switch ( type & ~T_UNSIGNED ) {
  215.             case TYPB:
  216.                 argval = getdisp(addr, 1, rn, amode);
  217.                 addr += 1;
  218.                 break;
  219.  
  220.             case TYPW:
  221.                 argval = getdisp(addr, 2, rn, amode);
  222.                 addr += 2;
  223.                 break;
  224.  
  225.             case TYPL:
  226.                 argval = getdisp(addr, 4, rn, amode);
  227.                 addr += 4;
  228.                 break;
  229.  
  230.             default:
  231.                 printf( "ERR: strange-autoinc %d\n", type );
  232.                 break;
  233.             }
  234.             }
  235.             break;
  236.  
  237.         case AUTOINCDEF:
  238.             if ( rn == PC ) {
  239.             /* immediate deferred */
  240.             argval = getdisp(addr, 4, rn, amode);
  241.             addr += 4;
  242.             } else {
  243.             reg_add( rn, type | T_POINTER, 0 );
  244.             }
  245.             break;
  246.  
  247.         case BYTEDISP:
  248.             argval = getdisp(addr, 1, rn, amode);
  249.             regdisp( rn, argval, type, fl );
  250.             addr += 1;
  251.             break;
  252.  
  253.         case BYTEDISPDEF:
  254.             argval = getdisp(addr, 1, rn, amode);
  255.             regdisp( rn, argval, type, fl );
  256.             addr += 1;
  257.             break;
  258.  
  259.         case WORDDISP:
  260.             argval = getdisp(addr, 2, rn, amode);
  261.             regdisp( rn, argval, type, fl );
  262.             addr += 2;
  263.             break;
  264.  
  265.         case WORDDISPDEF:
  266.             argval = getdisp(addr, 2, rn, amode);
  267.             regdisp( rn, argval, type, fl );
  268.             addr += 2;
  269.             break;
  270.  
  271.         case LONGDISP:
  272.             argval = getdisp(addr, 4, rn, amode);
  273.             regdisp( rn, argval, type, fl );
  274.             addr += 4;
  275.             break;
  276.  
  277.         case LONGDISPDEF:
  278.             argval = getdisp(addr, 4, rn, amode);
  279.             regdisp( rn, argval, type, fl );
  280.             addr += 4;
  281.             break;
  282.         }
  283.         if ( is_branch_disp( argtype ) )
  284.             llb_add( argval, FALSE );
  285.         }
  286.     }
  287.     if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) {
  288.         insaddr = addr;
  289.         for (argno = 0; argno <= argval; argno++) {
  290.         offset = get_word( addr );
  291.         addr += 2;
  292.         llb_add( insaddr+offset, TRUE );
  293.         }
  294.     }
  295.     }
  296. }
  297.  
  298.  
  299. /*
  300.  * Get the displacement of an instruction that uses displacement
  301.  * addressing.
  302.  */
  303.  
  304. static int
  305. getdisp(addr, nbytes, rn, mode)
  306. address addr;
  307. int nbytes;
  308. int rn;
  309. int mode;
  310. {
  311.     int argval;
  312.  
  313.     switch (nbytes) {
  314.     case 1:
  315.     argval = get_byte( addr );
  316.     break;
  317.  
  318.     case 2:
  319.     argval = get_word( addr );
  320.     break;
  321.  
  322.     case 4:
  323.     argval = get_long( addr );
  324.     break;
  325.     }
  326.     if (rn == PC && mode >= BYTEDISP) {
  327.     argval += addr + nbytes;
  328.     }
  329.     return argval;
  330. }
  331.  
  332. static
  333. regdisp( rn, offset, type, fl )
  334. int rn, offset, type, fl;
  335. {
  336.     switch ( rn ) {
  337.  
  338.     /* arguments */
  339.     case AP:
  340.     if ( offset < 0 )
  341.         fprintf( stderr, "bad argument offset %d\n", offset );
  342.     else
  343.         arg_add( offset, type, fl );
  344.     break;
  345.  
  346.     /* locals */
  347.     case FP:
  348.     if ( offset > 0 )
  349.         fprintf( stderr, "bad local offset %d\n", offset );
  350.     else
  351.         loc_add( -offset, type, fl );
  352.     break;
  353.  
  354.     case PC:
  355.     /* do nothing */
  356.     break;
  357.  
  358.     /* everything else */
  359.     default:
  360.     reg_add( rn, type | T_POINTER, 0 );
  361.     break;
  362.     }
  363. }
  364.